package com.jp.fm.service;

import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.eq;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import static org.junit.Assert.assertNotNull;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.easymock.EasyMock;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import com.jp.fm.EasyMockParent;
import com.jp.fm.dao.AccountDao;
import com.jp.fm.dao.TransactionDao;
import com.jp.fm.data.Account;
import com.jp.fm.data.Account.AccountBalance;
import com.jp.fm.data.AccountType;
import com.jp.fm.data.Category;
import com.jp.fm.data.Transaction;

public class PageServiceTest extends EasyMockParent {

	private PageService pageService = null;

	private HttpServletRequest mockRequest = null;
	private TransactionDao mockTransactionDao = null;
	private AccountDao mockAccountDao = null;
	private AccountService mockAccountService = null;

	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
	}

	@AfterClass
	public static void tearDownAfterClass() throws Exception {
	}

	@Before
	public void setUp() throws Exception {
		super.setUp();

		pageService = new PageService();
	}

	@After
	public void tearDown() throws Exception {
		super.tearDown();
	}

	@Test
	public final void testFindCreditAlerts() {

		List<Account> list = new ArrayList<Account>();
		Account acct = new Account(null, "test", null, null, null,
				new AccountBalance(null, Float.valueOf("5000"), null), 0);
		acct.setAvailableCredit(Float.valueOf("1000"));
		acct.setTotalCredit(Float.valueOf("6000"));
		list.add(acct);

		expect(mockAccountDao.findByType(anyObject(AccountType.class)))
				.andReturn(list);

		replayMocks();

		pageService.setAccountDao(mockAccountDao);
		List<String> ret = pageService.findCreditAlerts();

		assertNotNull(ret);
	}

	@Test
	public final void testComposeAccountBalancesOverTime() {

		List<Account> accts = new ArrayList<Account>();
		accts.add(new Account(null, "Visa", null, null, new AccountType(null,
				"Credit Cards", 0), null, 0));

		expect(mockAccountDao.findAll()).andReturn(accts);
		expect(mockAccountService.removeHiddenAccounts(accts)).andReturn(accts);

		expect(
				mockAccountDao.findAverageAccountBalanceForRange(
						anyObject(Date.class), anyObject(Date.class),
						anyObject(Account.class))).andReturn(
				Float.valueOf("100.99")).times(2);

		mockRequest.setAttribute(eq("accountAverageBalMap"), anyObject());
		expectLastCall();
		mockRequest.setAttribute(eq("balanceMonthList"), anyObject());
		expectLastCall();

		replayMocks();

		pageService.setAccountDao(mockAccountDao);
		pageService.setAccountService(mockAccountService);
		pageService.composeAccountBalancesOverTime(mockRequest, 1);
	}

	@Test
	public final void testComposeRequestLeftNav() {

		Class[] args = { HttpServletRequest.class };
		List<Account> accounts = new ArrayList<Account>();
		accounts.add(new Account(null, "test1", null, null, null,
				new AccountBalance(null, Float.valueOf("5000"), null), 0));
		accounts.add(new Account(null, "test2", null, null, null,
				new AccountBalance(null, Float.valueOf("200"), null), 1));

		PageService partialMockPageService = (PageService) createPartialMock(
				PageService.class, "composeRequestLeftNav", args, true);

		expect(
				mockAccountService
						.removeHiddenAccounts((List<Account>) anyObject()))
				.andReturn(accounts);
		mockRequest.setAttribute(eq("hiddenAccounts"), eq("true"));
		expectLastCall().times(1);
		expect(
				mockAccountService
						.removeHiddenAccounts((List<Account>) anyObject()))
				.andReturn(accounts);
		expect(
				partialMockPageService
						.recentAccountRefreshFailure((Account) anyObject()))
				.andReturn(false).anyTimes();

		mockRequest.setAttribute(eq("accountsWithErrors"),
				(List<Account>) anyObject());
		expectLastCall();
		mockRequest.setAttribute(eq("accountsByType"),
				(List<Account>) anyObject());
		expectLastCall();
		expect(mockRequest.getParameterValues("o")).andReturn(
				new String[] { "test" });
		mockRequest.setAttribute(eq("o"), anyObject());
		expectLastCall();

		replayMocks();
		EasyMock.replay(partialMockPageService);

		partialMockPageService.setAccountService(mockAccountService);

		partialMockPageService.composeRequestLeftNav(mockRequest);

		EasyMock.verify(partialMockPageService);
	}

	@Test
	public final void testComposeRequestNetIncome() {

		List<Transaction> list = new ArrayList<Transaction>();
		list.add(new Transaction(null, null, "Visa", Float.valueOf("100.00"),
				null, null, null, false, null));

		mockRequest.setAttribute(eq("monthLongEnd"), anyObject());
		expectLastCall();
		mockRequest.setAttribute(eq("monthTopCatsEnd"), anyObject());
		expectLastCall();
		expect(
				mockTransactionDao.findByAny(anyObject(Category.class),
						anyObject(Date.class), anyObject(Date.class),
						anyObject(String.class), anyObject(String.class),
						anyObject(Boolean.class))).andReturn(list).times(6);
		expect(mockAccountDao.findByName("Visa")).andReturn(
				new Account(null, "Visa", null, null, new AccountType(null,
						"Credit Cards", 0), null, 0)).times(6);
		mockRequest.setAttribute(eq("monthLongStart"), anyObject());
		expectLastCall();
		mockRequest.setAttribute(eq("monthTopCatsStart"), anyObject());
		expectLastCall();
		mockRequest.setAttribute(eq("trendList"), anyObject());
		expectLastCall();
		mockRequest.setAttribute(eq("sixMonthIncome"), anyObject());
		expectLastCall();
		mockRequest.setAttribute(eq("sixMonthSpent"), anyObject());
		expectLastCall();
		mockRequest.setAttribute(eq("sixMonthNet"), anyObject());
		expectLastCall();
		mockRequest.setAttribute(eq("monthMax"), anyObject());
		expectLastCall();

		replayMocks();

		pageService.setTransactionDao(mockTransactionDao);
		pageService.setAccountDao(mockAccountDao);
		pageService.composeRequestNetIncome(mockRequest);
	}

}
